package cn.mw.cmdb.service.interceptors;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.enums.ITSMAssetStateEnum;
import cn.mw.cmdb.exception.ProcessInterceptorException;
import cn.mw.cmdb.param.BatchAddAndUpdInstanceParam;
import cn.mw.cmdb.param.InstanceChangeRecordDTO;
import cn.mw.cmdb.processor.BusinessOperationService;
import cn.mw.cmdb.service.ModelService;
import cn.mw.cmdb.service.ServiceAction;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.microMonitorCommon.annotation.aop.FeatureFlow;
import cn.mw.microMonitorCommon.api.cmdb.MwCMDBCommonApi;
import cn.mw.microMonitorCommon.api.itsm.param.ItsmCommonParam;
import cn.mw.microMonitorCommon.constant.DateConstant;
import cn.mw.microMonitorCommon.entity.Constant;
import cn.mw.microMonitorCommon.flowable.annotations.ProcessMonitor;
import cn.mw.microMonitorCommon.flowable.annotations.ProcessParam;
import cn.mw.microMonitorCommon.util.SpringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.*;

import static cn.mw.cmdb.service.impl.InstanceServiceImpl.KEY_IDS;

@Service
@Slf4j
public class ProcessInterceptor implements ServiceInterceptor {

    private static final String ID = "instanceService";

    @Autowired
    private CmdbServiceManage cmdbServiceManage;

    @Autowired
    private BusinessOperationService businessOperationService;

    @Autowired
    private MwCMDBCommonApi mwCMDBCommonApi;

    @Override
    public boolean intercept(Object obj, ServiceAction action) throws Exception {
        ProcessInterceptor interceptor = SpringUtils.getBean(ProcessInterceptor.class);
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        try {
            boolean flag = false;
            Object ret = new Object();
            if (obj instanceof InstanceInfo) {
                switch (action) {
                    case add:
                        //验证参数,并设置线程变量
                        service.addAndUpdInstanceValidate((InstanceInfo) obj, true);
                        ret = interceptor.doInstanceAdd((InstanceInfo) obj, null);
                        flag = true;
                        break;
                    case update:
                        //验证参数,并设置线程变量
                        service.addAndUpdInstanceValidate((InstanceInfo) obj, false);
                        ret = interceptor.doInstanceUpdate((InstanceInfo) obj, null);
                        flag = true;
                        break;
                }
            }
            if (obj instanceof BatchAddAndUpdInstanceParam) {
                switch (action) {
                    case batchAdd:
                        List<InstanceInfo> instanceInfoList = service.batchAddInstanceParamConvert(obj);
                        //验证参数,并设置线程变量
                        service.batchAddAndUpdInstanceValidate(instanceInfoList, true, ((BatchAddAndUpdInstanceParam) obj));
                        Gson gson = new GsonBuilder()
                                .registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
                                    private SimpleDateFormat dateFormat = new SimpleDateFormat(DateConstant.NORM_DATETIME);

                                    @Override
                                    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
                                        return new JsonPrimitive(dateFormat.format(src));
                                    }
                                })
                                .create();;
                        String json = gson.toJson(instanceInfoList);
                        ItsmCommonParam itsmCommonParam = new ItsmCommonParam();
                        itsmCommonParam.setParamJson(json);
                        ret = interceptor.doInstanceBatchAdd(itsmCommonParam, null);
                        flag = true;
                        break;
                }
            }

            // 流程拦截后返回的MAP对象，直接抛出异常处理
            if (ret instanceof Map && ((Map) ret).containsKey(Constant.MSG)) {
                throw new ProcessInterceptorException();
            }
            if (flag) {
                log.info("记录拦截器实例操作日志 ...");
                businessOperationService.executeBusinessInstanceOperation(obj, ret, action);
                log.info("记录拦截器实例操作日志完成...");
                return true;
            }
        } catch (Exception e) {
            throw e;
        } finally {
            //清空线程变量,防止内存泄漏
            log.info("clean InstanceServiceImpl thread local");
            service.removeAddAndUpdInstanceContextThreadLocal();
        }
        return false;
    }

    @FeatureFlow(methodName = "新增实例")
    public Object doInstanceAdd(InstanceInfo param, @Param("processId") String processId) throws Exception {
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        List<InstanceInfo> list = (List<InstanceInfo>)service.add(param);
        return instanceChangeRecord(processId, list);
    }

    @FeatureFlow(methodName = "修改实例")
    public Object doInstanceUpdate(InstanceInfo param, @Param("processId") String processId) throws Exception {
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        service.update(param);
        return instanceChangeRecord(processId, param);
    }


    @FeatureFlow(methodName = "修改实例状态", ListUrl = "/mwapi/cmdb/processCall/getModelList", MapUrl = "/mwapi/cmdb/processCall/getModelFieldList", isMap = true)
    public Object doCustomUpdate(Map param, @Param("processId") String processId) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue((String) param.get(KEY_IDS), new TypeReference<List<Map>>() {
        });
        List<String> ids = new ArrayList<>();
        for (Map map : mapList) {
            ids.add((String) map.get("id"));
        }
        param.put(KEY_IDS, ids);
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        service.customUpdate(param);
        return param;
    }

    //    @FeatureFlow(methodName = "工单批量新增实例接口")
    @ProcessMonitor("资产入库")
    @ProcessParam("资产数据集合")
    public Object doInstanceITSMAdd(@ProcessParam("资产数据") ItsmCommonParam param) throws Exception {
        JSONArray jsonArray = JSON.parseArray(param.getParamJson());
        // 日志记录
        log.info("工单入库接口: {}", jsonArray.toJSONString());
        // 使用Jackson将JSON数组转换为Map列表
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue(jsonArray.toJSONString(), new TypeReference<List<Map>>() {});
        // 获取模型服务
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        // 将Map列表转换为InstanceInfo列表
        List<InstanceInfo> instanceInfoList = mapList.stream()
                .map(map -> {
                    try {
                        return (InstanceInfo) cmdbServiceManage.convert(modelService, map);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .toList();
        InstanceServiceImpl service = (InstanceServiceImpl) modelService;
        List<Map> instanceMapList = new ArrayList<>();
        for (InstanceInfo instanceInfo : instanceInfoList) {
            Map<String, Object> instanceMap = new HashMap<>();
            instanceMap.put("id", instanceInfo.getId());
            instanceMap.put(ITSMAssetStateEnum.ASSET_INVENTORY.getKey(), ITSMAssetStateEnum.ASSET_INVENTORY.getStateName());
            instanceMapList.add(instanceMap);
        }
        boolean b = service.batchUpdateByInstanceMap(instanceMapList);
        return b;
    }

    @ProcessMonitor("资产领用")
    @ProcessParam("资产数据集合")
    public Object assetAcquisition(@ProcessParam("资产数据") ItsmCommonParam param) throws Exception {
        JSONObject jsonObject = JSON.parseArray(param.getParamJson()).getJSONObject(0);
        // 日志记录
        log.info("工单领用接口: {}", jsonObject.toJSONString());
        // 使用Jackson将JSON数组转换为Map列表
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue( jsonObject.getJSONArray("type").toJSONString(), new TypeReference<List<Map>>() {});
        // 获取模型服务
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        // 将Map列表转换为InstanceInfo列表
        List<InstanceInfo> instanceInfoList = mapList.stream()
                .map(map -> {
                    try {
                        return (InstanceInfo) cmdbServiceManage.convert(modelService, map);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .toList();
        InstanceServiceImpl service = (InstanceServiceImpl) modelService;
        List<Map> instanceMapList = new ArrayList<>();
        for (InstanceInfo instanceInfo : instanceInfoList) {
            Map<String, Object> instanceMap = new HashMap<>();
            instanceMap.put("id", instanceInfo.getId());
            instanceMap.put(ITSMAssetStateEnum.ASSET_ACQUISITION.getKey(), ITSMAssetStateEnum.ASSET_ACQUISITION.getStateName());
            instanceMap.put("mw_manager", jsonObject.get("mw_manager"));
            instanceMap.put("mw_administration_department", jsonObject.get("mw_administration_department"));
            instanceMap.put("mw_user_department", jsonObject.get("mw_user_department"));
            instanceMap.put("mw_use_people", jsonObject.get("mw_use_people"));
            instanceMapList.add(instanceMap);
        }
        boolean b = service.batchUpdateByInstanceMap(instanceMapList);
        return b;
    }

    @ProcessMonitor("资产维修")
    @ProcessParam("资产数据集合")
    public Object assetMaintenance(@ProcessParam("资产数据") ItsmCommonParam param) throws Exception {
        JSONArray jsonArray = JSON.parseArray(param.getParamJson());
        // 日志记录
        log.info("工单维修接口: {}", jsonArray.toJSONString());
        // 使用Jackson将JSON数组转换为Map列表
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue(jsonArray.toJSONString(), new TypeReference<List<Map>>() {});
        // 获取模型服务
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        // 将Map列表转换为InstanceInfo列表
        List<InstanceInfo> instanceInfoList = mapList.stream()
                .map(map -> {
                    try {
                        return (InstanceInfo) cmdbServiceManage.convert(modelService, map);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .toList();
        InstanceServiceImpl service = (InstanceServiceImpl) modelService;
        List<Map> instanceMapList = new ArrayList<>();
        for (InstanceInfo instanceInfo : instanceInfoList) {
            Map<String, Object> instanceMap = new HashMap<>();
            instanceMap.put("id", instanceInfo.getId());
            instanceMap.put(ITSMAssetStateEnum.ASSET_REPAIR.getKey(), ITSMAssetStateEnum.ASSET_REPAIR.getStateName());
            instanceMapList.add(instanceMap);
        }
        boolean b = service.batchUpdateByInstanceMap(instanceMapList);
        return b;
    }

    @ProcessMonitor("资产报废")
    @ProcessParam("资产数据集合")
    public Object assetRetirement(@ProcessParam("资产数据") ItsmCommonParam param) throws Exception {
        JSONArray jsonArray = JSON.parseArray(param.getParamJson());
        // 日志记录
        log.info("工单报废接口: {}", jsonArray.toJSONString());
        // 使用Jackson将JSON数组转换为Map列表
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue(jsonArray.toJSONString(), new TypeReference<List<Map>>() {});
        // 获取模型服务
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        // 将Map列表转换为InstanceInfo列表
        List<InstanceInfo> instanceInfoList = mapList.stream()
                .map(map -> {
                    try {
                        return (InstanceInfo) cmdbServiceManage.convert(modelService, map);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .toList();
        InstanceServiceImpl service = (InstanceServiceImpl) modelService;
        List<Map> instanceMapList = new ArrayList<>();
        for (InstanceInfo instanceInfo : instanceInfoList) {
            Map<String, Object> instanceMap = new HashMap<>();
            instanceMap.put("id", instanceInfo.getId());
            instanceMap.put(ITSMAssetStateEnum.ASSET_SCRAPPED.getKey(), ITSMAssetStateEnum.ASSET_SCRAPPED.getStateName());
            instanceMapList.add(instanceMap);
        }
        boolean b = service.batchUpdateByInstanceMap(instanceMapList);
        return b;
    }

//    @FeatureFlow(methodName = "工单批量修改实例接口")
@ProcessMonitor("工单批量修改实例接口")
@ProcessParam("资产数据集合")
public Object doInstanceITSMUpdateBatch(@ProcessParam("资产数据") ItsmCommonParam param) throws Exception {
    String processId = null;

    List<InstanceInfo> list = new ArrayList<>();
    log.info("工单批量修改实例接口:" + param.getParamJson());
    ObjectMapper objectMapper = new ObjectMapper();
    List<Map> mapList = objectMapper.readValue(param.getParamJson(), new TypeReference<List<Map>>() {
    });
    ModelService modelService = cmdbServiceManage.getModelService(ID);
    for (Map map : mapList) {
        Object convert = cmdbServiceManage.convert(modelService, map);
        if (convert != null && convert instanceof InstanceInfo) {
            InstanceInfo instanceInfo = (InstanceInfo) convert;
                list.add(instanceInfo);
            }
        }
        log.info("工单批量修改实例转换参数::"+list);
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        Object o = service.doBatchUpdateMulti(list);
        return instanceChangeRecord(processId, list);
    }

    @FeatureFlow(methodName = "工单修改实例接口")
    public Object doInstanceITSMUpdate(ItsmCommonParam param, @Param("processId") String processId) throws Exception {
        List<InstanceInfo> list = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue(param.getParamJson(), new TypeReference<List<Map>>() {
        });
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        for (Map map : mapList) {
            Object convert = cmdbServiceManage.convert(modelService, map);
            if (convert != null && convert instanceof InstanceInfo) {
                InstanceInfo instanceInfo = (InstanceInfo) convert;
                list.add(instanceInfo);
            }
        }
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        service.update(list.get(0));
        return instanceChangeRecord(processId, list.get(0));
    }

    @FeatureFlow(methodName = "批量新增实例接口")
    public  Object doInstanceBatchAdd(ItsmCommonParam param, @Param("processId") String processId) throws Exception {
        List<InstanceInfo> list = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map> mapList = objectMapper.readValue(param.getParamJson(), new TypeReference<List<Map>>() {
        });
        log.info("批量新增实例接口11::"+mapList);
        ModelService modelService = cmdbServiceManage.getModelService(ID);
        for (Map map : mapList) {
            Object convert = cmdbServiceManage.convert(modelService, map);
            if (convert != null && convert instanceof InstanceInfo) {
                InstanceInfo instanceInfo = (InstanceInfo) convert;
                list.add(instanceInfo);
            }
        }
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        Object resultData = service.doBatchAdd(list);
        if(resultData!=null && resultData instanceof List){
            List<InstanceInfo> listInfp = (List<InstanceInfo>) resultData;
            return instanceChangeRecord(processId,listInfp);
        }
        return instanceChangeRecord(processId, list);

    }

    public InstanceChangeRecordDTO instanceChangeRecord(String processId, List<InstanceInfo> list) {
        InstanceChangeRecordDTO dto = new InstanceChangeRecordDTO();
        dto.setProcessId(processId);
        dto.setInstanceInfos(list);
        return dto;
    }

    public InstanceChangeRecordDTO instanceChangeRecord(String processId, InstanceInfo instanceInfo) {
        InstanceChangeRecordDTO dto = new InstanceChangeRecordDTO();
        dto.setProcessId(processId);
        dto.setInstanceInfos(Collections.singletonList(instanceInfo));
        return dto;
    }

}
